home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 008a / emslb221.zip / EMSTEST.C < prev    next >
C/C++ Source or Header  |  1991-10-13  |  89KB  |  2,056 lines

  1. /***************************************************************************
  2. *   emstest.c                                                              *
  3. *   MODULE:  EMSLIB                                                        *
  4. *   OS:      DOS                                                           *
  5. *   VERSION: 1.0                                                           *
  6. *   DATE:    09/25/91                                                      *
  7. *                                                                          *
  8. *   Copyright (c) 1991 James W. Birdsall. All Rights Reserved.             *
  9. *                                                                          *
  10. *   Requires emslib.h and emstest.h to compile.                            *
  11. *   Compiles under Borland C++ 2.0 or MSC 6.00A.                           *
  12. *                                                                          *
  13. *   Regression test and example for EMSLIB.                                *
  14. *                                                                          *
  15. *   This is part one of the regression tester and example for EMSLIB.      *
  16. *   The other parts are named EMSTEST2.C and EMSTEST3.C. All three parts   *
  17. *   must be compiled and linked together along with the appropriate EMSLIB *
  18. *   library to produce the tester executable. This program compiles under  *
  19. *   tiny, small, medium, compact, large, and huge models. Note that it     *
  20. *   doesn't quite fit into tiny model; the tiny model tester is actually   *
  21. *   three executables. When compiling for tiny model, one of the symbols   *
  22. *   TINYPASS1, TINYPASS2, or TINYPASS3 must be defined. See the example    *
  23. *   makefiles for further details on what needs to be linked with what     *
  24. *   to produce the tiny-model executables.                                 *
  25. *                                                                          *
  26. *   To use this tester: just run it. It requires no arguments and produces *
  27. *   output on stdout. It performs nearly 200 tests and parts of it run     *
  28. *   quite fast, even on an original IBM PC/XT (4.77 MHz). If you want to   *
  29. *   actually read the output, you should redirect the output to a file.    *
  30. *   If you just want to see whether the tests all pass, just run it --     *
  31. *   if a test fails, execution aborts immediately.                         *
  32. *                                                                          *
  33. *   Certain types of failure may cause EMSTEST to not deallocate EMS or    *
  34. *   conventional memory that it has allocated. This should only occur if   *
  35. *   the library itself is malfunctioning (which should never happen to     *
  36. *   you, only to me!) or if you are trying a different compiler or         *
  37. *   unsupported memory model and the compiler and library are therefore    *
  38. *   not communicating properly. It may also happen if you press control-   *
  39. *   break.                                                                 *
  40. *                                                                          *
  41. *   To improve speed, some basic functions are coded in in-line assembly   *
  42. *   language. The in-line assembly is compatible with Turbo/Borland C[++]  *
  43. *   and MSC 6.00A. Since earlier versions of Turbo C required an external  *
  44. *   assembler to support in-line assembly, and I don't know whether        *
  45. *   earlier versions of MSC supported it at all, the functions also have   *
  46. *   alternate C versions. The C versions are compiled by default; to get   *
  47. *   the in-line assembly versions, you must define the symbol INLINE_ASM.  *
  48. *                                                                          *
  49. *   Turbo C and older versions of Turbo C++ do not have the _fmemcmp() and *
  50. *   _fmemset() functions; I don't know about older versions of MSC. If     *
  51. *   your compiler does not have these functions, define the symbol         *
  52. *   NO_FFUNC and functions in this file will be used instead.              *
  53. *                                                                          *
  54. ***************************************************************************/
  55.  
  56. /*
  57. ** system includes <>
  58. */
  59.  
  60. #include <stdio.h>
  61. #include <stdlib.h>
  62. #include <dos.h>
  63. #include <string.h>
  64.  
  65.  
  66. /*
  67. ** custom includes ""
  68. */
  69.  
  70. #include "emslib.h"
  71. #include "emstest.h"
  72.  
  73.  
  74. /*
  75. ** local #defines
  76. */
  77.  
  78. /*
  79. ** misc: copyright strings, version macros, etc.
  80. */
  81.  
  82. /*
  83. ** typedefs
  84. */
  85.  
  86. /*
  87. ** global variables
  88. */
  89.  
  90. int testno = 1;                     /* number of test currently being done  */
  91. unsigned char far *frameptr[4];     /* pointers to EMS frames               */
  92. char *gblmsg = "";                  /* msg to be printed in test header     */
  93.  
  94.  
  95. /*
  96. ** static globals
  97. */
  98.  
  99. /*
  100. ** function prototypes
  101. */
  102.  
  103. static unsigned char huge *normptr(unsigned char far *norm);
  104.  
  105.  
  106. /*
  107. ** functions
  108. */
  109.  
  110.  
  111. /***************************************************************************
  112. *   FUNCTION: MAIN                                                         *
  113. *                                                                          *
  114. *   DESCRIPTION:                                                           *
  115. *                                                                          *
  116. *       The master function.                                               *
  117. *                                                                          *
  118. *   ENTRY:                                                                 *
  119. *                                                                          *
  120. *       None.                                                              *
  121. *                                                                          *
  122. *   EXIT:                                                                  *
  123. *                                                                          *
  124. *       Void.                                                              *
  125. *                                                                          *
  126. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  127. *                                                                          *
  128. ***************************************************************************/
  129. main()
  130. {
  131.     int status;                     /* return status from library functions */
  132.  
  133.     /*
  134.     ** check initialization test
  135.     */
  136.     TESTHEADER();
  137.     printf("Making a call to EMMgetversion() before calling EMMlibinit().\n");
  138.     printf("The call should fail.\n");
  139.     EMMgetversion();
  140.     nofailcheck("EMMgetversion()", (int) _EMMerror, NULL, 0, 0);
  141.     weirdcodechk("EMMgetversion()", EMM_NOINIT, NULL, 0, 0);
  142.     TESTTAILER();
  143.  
  144.  
  145.     /*
  146.     ** initialize EMSLIB
  147.     */
  148.     TESTHEADER();
  149.     printf("Calling EMMlibinit().\n");
  150.     printf("Should succeed if Expanded Memory Manager is present.\n");
  151.     status = EMMlibinit();
  152.     switch (status)
  153.     {
  154.         case EMMOOPS:
  155.             printf("EMMlibinit() failed, code 0x%X.\n",
  156.                                                     (unsigned int) _EMMerror);
  157.             exit(3);
  158.             break;
  159.  
  160.         case NOEMM:
  161.             printf("EMMlibinit() did not find an Expanded Memory Manager.\n");
  162.             exit(3);
  163.             break;
  164.  
  165.         case 0:
  166.             printf("EMMlibinit() returned OK.\n");
  167.             weirdcodechk("EMMlibinit()", 0, NULL, 0, 0);
  168.             break;
  169.  
  170.         default:
  171.             printf("EMMlibinit() returned strange value %d.\n", status);
  172.             exit(3);
  173.             break;
  174.     }
  175.     TESTTAILER();
  176.  
  177. /*
  178. ** The following section of code is included only in the first tiny-model
  179. ** executable and in non-tiny-model executables.
  180. */
  181. #ifndef TINYPASS2
  182. #ifndef TINYPASS3
  183.  
  184.     /*
  185.     ** test version call
  186.     */
  187.     TESTHEADER();
  188.     printf("Testing EMMgetversion().\n");
  189.     printf("Results should match value in _EMMversion.\n");
  190.     status = EMMgetversion();
  191.     weirdcodechk("EMMgetversion()", 0, NULL, 0, 0);
  192.     if (status != (int) _EMMversion)
  193.     {
  194.         printf("EMMgetversion() [0x%X] and _EMMversion [0x%X] differ.\n",
  195.                                            status, (unsigned int) _EMMversion);
  196.         exit(3);
  197.     }
  198.     printf("EMS version %d.%d.\n", ((status >> 4) & 0xF), (status & 0xF));
  199.     TESTTAILER();
  200.  
  201.  
  202.     /*
  203.     ** test allocation functions
  204.     */
  205.     do_alloc_tests(1L);
  206.     do_alloc_tests(16384L);
  207.     do_alloc_tests(55555L);
  208.     do_alloc_tests(0L);
  209.  
  210.     do_palloc_tests(1);
  211.     do_palloc_tests(5);
  212.  
  213. #endif
  214. #endif
  215.  
  216.     /*
  217.     ** test frame functions -- included in all executables
  218.     */
  219.     do_frame_tests();
  220.  
  221. /*
  222. ** The following section of code is included only in the first tiny-model
  223. ** executable and in non-tiny-model executables.
  224. */
  225. #ifndef TINYPASS2
  226. #ifndef TINYPASS3
  227.  
  228.     /*
  229.     ** test name functions
  230.     */
  231.     do_name_tests();
  232.  
  233.     /*
  234.     ** do mapping tests
  235.     */
  236.     do_map_tests();
  237.  
  238.     /*
  239.     ** test the save/restore facility
  240.     */
  241.     do_sr_tests();
  242.  
  243. #endif
  244. #endif
  245.  
  246. /*
  247. ** The following section of code is included only in the second tiny-model
  248. ** executable and in non-tiny-model executables.
  249. */
  250. #ifndef TINYPASS1
  251. #ifndef TINYPASS3
  252.  
  253.     /*
  254.     ** test copies of <= one page, frame caching on
  255.     */
  256.     gblmsg = "  SHORT COPY TESTS";
  257.     do_shortcopy_tests();
  258.     gblmsg = "";
  259.  
  260.     /*
  261.     ** test frame cache control
  262.     */
  263.     TESTHEADER();
  264.     printf("Testing frame caching enable/disable.\n");
  265.     if (_EMMframecache == 0)
  266.     {
  267.         printf("Frame caching is supposed to be on by default, seems to ");
  268.         printf("be off.\n");
  269.         exit(3);
  270.     }
  271.     _EMMdisc();
  272.     weirdcodechk("_EMMdisc()", 0, NULL, 0, 0);
  273.     if (_EMMframecache != 0)
  274.     {
  275.         printf("_EMMdisc() did not disable frame caching.\n");
  276.         exit(3);
  277.     }
  278.     _EMMenc();
  279.     weirdcodechk("_EMMenc()", 0, NULL, 0, 0);
  280.     if (_EMMframecache == 0)
  281.     {
  282.         printf("_EMMenc() did not enable frame caching.\n");
  283.         exit(3);
  284.     }
  285.     printf("Flag and function calls correspond OK.\n");
  286.     TESTTAILER();
  287.  
  288.     /*
  289.     ** test copies of <= one page, frame caching off
  290.     */
  291.     _EMMdisc();
  292.     gblmsg = "  SHORT COPY TESTS WITH FRAME CACHING OFF";
  293.     do_shortcopy_tests();
  294.     _EMMenc();
  295.  
  296. #endif
  297.  
  298. /*
  299. ** The following section of code is included only in the third tiny-model
  300. ** executable and in non-tiny-model executables.
  301. */
  302. #ifndef TINYPASS2
  303.  
  304.     /*
  305.     ** test copies of > 1 page, frame caching on
  306.     */
  307.     _EMMenc();
  308.     gblmsg = "  LONG COPY TESTS";
  309.     do_longcopy_tests();
  310.  
  311.     /*
  312.     ** test copies of > 1 page, frame caching off
  313.     */
  314.     _EMMdisc();
  315.     gblmsg = "  LONG COPY TESTS WITH FRAME CACHING OFF";
  316.     do_longcopy_tests();
  317.     gblmsg = "";
  318.     _EMMenc();
  319.  
  320. #endif
  321. #endif
  322.  
  323.     /* end and cleanup */
  324.     printf(">>>END\n");
  325.     printf("All tests succeeded.\n");
  326.  
  327.     exit(0);
  328. } /* end of main() */
  329.  
  330.  
  331. /***************************************************************************
  332. *   FUNCTION: DO_FRAME_TESTS                                               *
  333. *                                                                          *
  334. *   DESCRIPTION:                                                           *
  335. *                                                                          *
  336. *       This function tests EMSLIB calls EMMgetnumframe(),                 *
  337. *       EMMgetframeaddr(), and EMMgetsinfraddr().                          *
  338. *                                                                          *
  339. *   ENTRY:                                                                 *
  340. *                                                                          *
  341. *       Void.                                                              *
  342. *                                                                          *
  343. *   EXIT:                                                                  *
  344. *                                                                          *
  345. *       Void.                                                              *
  346. *                                                                          *
  347. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  348. *                                                                          *
  349. *       Fills in the frameptr[] global array.                              *
  350. *                                                                          *
  351. ***************************************************************************/
  352. void do_frame_tests(void)
  353. {
  354.     frameinfo *framebuf;
  355.     int frames;
  356.     int status;
  357.     int loop;
  358.     unsigned int segaddr;
  359.  
  360.     /* get number of frames */
  361.     TESTHEADER();
  362.     printf("Getting number of frames with EMMgetnumframe().\n");
  363.     if (_EMMversion < 0x40)
  364.     {
  365.         printf("Should be exactly 4.\n");
  366.     }
  367.     else
  368.     {
  369.         printf("Should be 4 or more.\n");
  370.     }
  371.     frames = EMMgetnumframe();
  372.     weirdcodechk("EMMgetnumframe()", 0, NULL, 0, 0);
  373.     if (frames < 4)
  374.     {
  375.         printf("EMMgetnumframe() returned OK but indicates only %d frames.\n",
  376.                                                                        frames);
  377.         exit(3);
  378.     }
  379.     if ((_EMMversion < 0x40) && (frames != 4))
  380.     {
  381.         printf("EMMgetnumframe() returned OK but indicates wrong number of\n");
  382.         printf("   frames (%d) for this version.\n", frames);
  383.         exit(3);
  384.     }
  385.     printf("EMMgetnumframe() returned OK, %d frames.\n", frames);
  386.     TESTTAILER();
  387.  
  388.     /* allocate memory for frame address buffer */
  389.     framebuf = (frameinfo *) calloc(frames, sizeof(frameinfo));
  390.     if (framebuf == (frameinfo *) NULL)
  391.     {
  392.         printf("OOPS! Couldn't allocate a buffer. Aborting.\n");
  393.         exit(3);
  394.     }
  395.  
  396.     /* get frame segment addresses */
  397.     TESTHEADER();
  398.     printf("Getting frame address info with EMMgetframeaddr().\n");
  399.     printf("Should succeed.\n");
  400.     status = EMMgetframeaddr(framebuf);
  401.     TRIPLECHECK("EMMgetframeaddr()", status, 0, framebuf, 0, 0);
  402.     printf("EMMgetframeaddr() returned OK, checking info returned...\n");
  403.     for (loop = 0; loop < frames; loop++)
  404.     {
  405.         /* check for valid frame number */
  406.         if (framebuf[loop].frameno >= frames)
  407.         {
  408.             printf("Frame number in slot %d is bad (%u).\n", loop,
  409.                                                        framebuf[loop].frameno);
  410.             free(framebuf);
  411.             exit(3);
  412.         }
  413.         /* check that frame segment address is on a page (16K) boundary */
  414.         if ((framebuf[loop].segaddr & 0x3FF) != 0)
  415.         {
  416.             printf(
  417.              "Frame segment %u, slot %d, frame number %u, not page aligned.\n",
  418.              framebuf[loop].segaddr, loop, framebuf[loop].frameno);
  419.             free(framebuf);
  420.             exit(3);
  421.         }
  422.         /* if one of frames 0-3, save the address */
  423.         if (framebuf[loop].frameno < 4)
  424.         {
  425.             frameptr[framebuf[loop].frameno] = (unsigned char far *)
  426.                                               MK_FP(framebuf[loop].segaddr, 0);
  427.         }
  428.     }
  429.     printf("Info returned checks out OK.\n");
  430.     TESTTAILER();
  431.  
  432.     /* now test EMMgetsinfraddr() */
  433.     TESTHEADER();
  434.     printf("Testing EMMgetsinfraddr() against data from EMMgetframeaddr().\n");
  435.     printf("Should succeed.\n");
  436.     /* loop through framebuf, calling EMMgetsinfraddr() on each */
  437.     for (loop = 0; loop < frames; loop++)
  438.     {
  439.         segaddr = EMMgetsinfraddr(framebuf[loop].frameno);
  440.         weirdcodechk("EMMgetsinfraddr()", 0, framebuf, 0, 0);
  441.         if (segaddr != framebuf[loop].segaddr)
  442.         {
  443.             printf("EMMgetsinfraddr(%u) succeeded but returned %u, not %u.\n",
  444.                       framebuf[loop].frameno, segaddr, framebuf[loop].segaddr);
  445.             free(framebuf);
  446.             exit(3);
  447.         }
  448.     }
  449.     printf("EMMgetsinfraddr() returned all addresses OK.\n");
  450.     TESTTAILER();
  451.  
  452.     /* clean up */
  453.     free(framebuf);
  454.  
  455.     return;
  456. } /* end of do_frame_tests() */
  457.  
  458.  
  459. /*
  460. ** The following section of code is included only in the first tiny-model
  461. ** executable and in non-tiny-model executables.
  462. */
  463. #ifndef TINYPASS2
  464. #ifndef TINYPASS3
  465.  
  466.  
  467. /***************************************************************************
  468. *   FUNCTION: DO_ALLOC_TESTS                                               *
  469. *                                                                          *
  470. *   DESCRIPTION:                                                           *
  471. *                                                                          *
  472. *       This function tests EMSLIB calls EMMcoreleft(), EMMalloc(), and    *
  473. *       EMMfree().                                                         *
  474. *                                                                          *
  475. *   ENTRY:                                                                 *
  476. *                                                                          *
  477. *       bytes - number of bytes of EMS to try to allocate.                 *
  478. *                                                                          *
  479. *   EXIT:                                                                  *
  480. *                                                                          *
  481. *       Void.                                                              *
  482. *                                                                          *
  483. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  484. *                                                                          *
  485. ***************************************************************************/
  486. void do_alloc_tests(unsigned long bytes)
  487. {
  488.     unsigned long emsfree, emsfree2;
  489.     unsigned long pagelen;
  490.     int handle;
  491.  
  492.     /* get bytes value rounded up to nearest page, or 1 page if bytes == 0 */
  493.     if (bytes != 0L)
  494.     {
  495.         pagelen = bytes + 16383L;
  496.         pagelen &= 0xFFFFC000L;
  497.     }
  498.     else
  499.     {
  500.         pagelen = 16384L;
  501.     }
  502.  
  503.     /* test coreleft */
  504.     TESTHEADER();
  505.     printf("Testing EMMcoreleft().\n");
  506.     printf("Result should be multiple of 16384.\n");
  507.     emsfree = test_EMMcoreleft();
  508.     printf("EMMcoreleft() returned OK, shows %lu bytes (%lu pages) free.\n",
  509.                                                   emsfree, (emsfree / 16384L));
  510.     TESTTAILER();
  511.  
  512.     /* make sure enough free */
  513.     if (emsfree < (MINFREE * 16384L))
  514.     {
  515.         printf("Insufficient free EMS to perform all tests. Aborting.\n");
  516.         exit(1);
  517.     }
  518.  
  519.     /* test allocation */
  520.     TESTHEADER();
  521.     printf("Testing EMMalloc(%lu).\n", bytes);
  522.     printf("Should succeed. Free EMS should drop by %lu bytes (%lu pages).\n",
  523.                                                   pagelen, (pagelen / 16384L));
  524.     handle = test_EMMalloc(bytes);
  525.     printf("EMMalloc() returned OK.\n");
  526.     emsfree2 = test_EMMcoreleft();
  527.     printf("EMMcoreleft() returned OK, shows %lu bytes (%lu pages) free.\n",
  528.                                                 emsfree2, (emsfree2 / 16384L));
  529.     if ((emsfree - emsfree2) != pagelen)
  530.     {
  531.         printf("EMMalloc(%lu) caused free to drop weirdly from %lu to %lu.\n",
  532.                                                      bytes, emsfree, emsfree2);
  533.         EMMfree(handle);
  534.         exit(3);
  535.     }
  536.     TESTTAILER();
  537.  
  538.     /* test free */
  539.     TESTHEADER();
  540.     printf("Testing EMMfree() on handle just returned by EMMalloc().\n");
  541.     printf(
  542.         "Should succeed. Free EMS should increase by %lu bytes (%lu pages).\n",
  543.         pagelen, (pagelen / 16384L));
  544.     test_EMMfree(handle);
  545.     printf("EMMfree() returned OK.\n");
  546.     emsfree2 = test_EMMcoreleft();
  547.     printf("EMMcoreleft() returned OK, shows %lu bytes (%lu pages) free.\n",
  548.                                                 emsfree2, (emsfree2 / 16384L));
  549.     if (emsfree2 != emsfree)
  550.     {
  551.         printf("Freeing handle returned by EMMalloc() did not restore\n");
  552.         printf("   free EMS count -- was %lu originally, now %lu.\n", emsfree,
  553.                                                                      emsfree2);
  554.         exit(3);
  555.     }
  556.     TESTTAILER();
  557.  
  558.     return;
  559. } /* end of do_alloc_tests() */
  560.  
  561.  
  562. /***************************************************************************
  563. *   FUNCTION: DO_PALLOC_TESTS                                              *
  564. *                                                                          *
  565. *   DESCRIPTION:                                                           *
  566. *                                                                          *
  567. *       This function tests EMSLIB calls EMMcoreleft(), EMMallocpages(),   *
  568. *       and EMMfree().                                                     *
  569. *                                                                          *
  570. *   ENTRY:                                                                 *
  571. *                                                                          *
  572. *       pages - number of pages of EMS to try to allocate.                 *
  573. *                                                                          *
  574. *   EXIT:                                                                  *
  575. *                                                                          *
  576. *       Void.                                                              *
  577. *                                                                          *
  578. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  579. *                                                                          *
  580. ***************************************************************************/
  581. void do_palloc_tests(int pages)
  582. {
  583.     unsigned long emsfree, emsfree2;
  584.     unsigned long pagelen;
  585.     int handle;
  586.  
  587.     /* convert pages to bytes */
  588.     pagelen = 16384L * pages;
  589.  
  590.     /* test coreleft */
  591.     TESTHEADER();
  592.     printf("Testing EMMcoreleft().\n");
  593.     printf("Result should be multiple of 16384.\n");
  594.     emsfree = test_EMMcoreleft();
  595.     printf("EMMcoreleft() returned OK, shows %lu bytes (%lu pages) free.\n",
  596.                                                   emsfree, (emsfree / 16384L));
  597.     TESTTAILER();
  598.  
  599.     /* make sure enough free */
  600.     if (emsfree < (MINFREE * 16384L))
  601.     {
  602.         printf("Insufficient free EMS to perform all tests. Aborting.\n");
  603.         exit(1);
  604.     }
  605.  
  606.     /* test allocation */
  607.     TESTHEADER();
  608.     printf("Testing EMMallocpages(%d).\n", pages);
  609.     printf("Should succeed. Free EMS should drop by %lu bytes (%lu pages).\n",
  610.                                                   pagelen, (pagelen / 16384L));
  611.     handle = test_EMMallocpages(pages);
  612.     printf("EMMallocpages() retured OK.\n");
  613.     emsfree2 = test_EMMcoreleft();
  614.     printf("EMMcoreleft() returned OK, shows %lu bytes (%lu pages) free.\n",
  615.                                                 emsfree2, (emsfree2 / 16384L));
  616.     if ((emsfree - emsfree2) != pagelen)
  617.     {
  618.         printf(
  619.             "EMMallocpages(%d) caused free to drop weirdly from %lu to %lu.\n",
  620.             pages, emsfree, emsfree2);
  621.         EMMfree(handle);
  622.         exit(3);
  623.     }
  624.     TESTTAILER();
  625.  
  626.     /* test free */
  627.     TESTHEADER();
  628.     printf("Testing EMMfree() on handle just returned by EMMallocpages().\n");
  629.     printf(
  630.         "Should succeed. Free EMS should increase by %lu bytes (%lu pages).\n",
  631.         pagelen, (pagelen / 16384L));
  632.     test_EMMfree(handle);
  633.     printf("EMMfree() returned OK.\n");
  634.     emsfree2 = test_EMMcoreleft();
  635.     printf("EMMcoreleft() returned OK, shows %lu bytes (%lu pages) free.\n",
  636.                                                 emsfree2, (emsfree2 / 16384L));
  637.     if (emsfree2 != emsfree)
  638.     {
  639.         printf("Freeing handle returned by EMMallocpages() did not restore\n");
  640.         printf("   free EMS count -- was %lu originally, now %lu.\n", emsfree,
  641.                                                                      emsfree2);
  642.         exit(3);
  643.     }
  644.     TESTTAILER();
  645.  
  646.     return;
  647. } /* end of do_palloc_tests() */
  648.  
  649.  
  650. /***************************************************************************
  651. *   FUNCTION: DO_NAME_TESTS                                                *
  652. *                                                                          *
  653. *   DESCRIPTION:                                                           *
  654. *                                                                          *
  655. *       This function tests EMSLIB calls EMMgetname() and EMMsetname().    *
  656. *                                                                          *
  657. *   ENTRY:                                                                 *
  658. *                                                                          *
  659. *       Void.                                                              *
  660. *                                                                          *
  661. *   EXIT:                                                                  *
  662. *                                                                          *
  663. *       Void.                                                              *
  664. *                                                                          *
  665. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  666. *                                                                          *
  667. ***************************************************************************/
  668. void do_name_tests(void)
  669. {
  670.     char name[9];
  671.     int handle, status;
  672.  
  673.     TESTHEADER();
  674.     printf("Testing EMMsetname() and EMMgetname().\n");
  675.     if (_EMMversion < 0x40)
  676.     {
  677.         printf(
  678.               "EMMsetname() should fail, EMMgetname() return empty buffer.\n");
  679.     }
  680.     else
  681.     {
  682.         printf("Should succeed.\n");
  683.     }
  684.     /* allocate some EMS to assign a name to */
  685.     handle = test_EMMalloc(16384);
  686.     printf("Calling EMMsetname() with name ABCDEFGH.\n");
  687.     status = EMMsetname(handle, "ABCDEFGH");
  688.     if (_EMMversion < 0x40)
  689.     {
  690.         nofailcheck("EMMsetname()", status, NULL, handle, 0);
  691.         weirdretchk("EMMsetname()", status, NULL, handle, 0);
  692.         weirdcodechk("EMMsetname()", EMM_BADVERS, NULL, handle, 0);
  693.         printf("EMMsetname() failed OK.\n");
  694.     }
  695.     else
  696.     {
  697.         TRIPLECHECK("EMMsetname()", status, 0, NULL, handle, 0);
  698.         printf("EMMsetname() succeeded.\n");
  699.     }
  700.     printf("Now calling EMMgetname().\n");
  701.     status = EMMgetname(handle, name);
  702.     TRIPLECHECK("EMMgetname()", status, 0, NULL, handle, 0);
  703.     if (_EMMversion < 0x40)
  704.     {
  705.         if (farmemcheck((unsigned char far *) name, 9, '\0') != 0)
  706.         {
  707.             printf("A character in name is not null.\n");
  708.             EMMfree(handle);
  709.             exit(3);
  710.         }
  711.     }
  712.     else
  713.     {
  714.         if (strcmp(name, "ABCDEFGH") != 0)
  715.         {
  716.             printf("Got name %s back.\n", name);
  717.             EMMfree(handle);
  718.             exit(3);
  719.         }
  720.     }
  721.     printf("EMMgetname() succeeded.\n");
  722.     test_EMMfree(handle);
  723.     TESTTAILER();
  724.  
  725.     return;
  726. } /* end of do_name_tests() */
  727.  
  728.  
  729. /***************************************************************************
  730. *   FUNCTION: DO_MAP_TESTS                                                 *
  731. *                                                                          *
  732. *   DESCRIPTION:                                                           *
  733. *                                                                          *
  734. *       This function tests EMSLIB call EMMmappage().                      *
  735. *                                                                          *
  736. *   ENTRY:                                                                 *
  737. *                                                                          *
  738. *       Void.                                                              *
  739. *                                                                          *
  740. *   EXIT:                                                                  *
  741. *                                                                          *
  742. *       Void.                                                              *
  743. *                                                                          *
  744. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  745. *                                                                          *
  746. ***************************************************************************/
  747. void do_map_tests(void)
  748. {
  749.     int handle1, handle2;
  750.     int loop;
  751.     int status;
  752.  
  753.     /* first, allocate some EMS to map */
  754.     handle1 = test_EMMallocpages(6);
  755.     handle2 = test_EMMallocpages(2);
  756.  
  757.     /* initial test of EMMmappage() */
  758.     TESTHEADER();
  759.     printf("Calling EMMmappage(frameno = 0, first handle, logpage = 0).\n");
  760.     printf("Should succeed.\n");
  761.     test_EMMmappage(0, handle1, 0);
  762.     printf("EMMmappage() returned OK.\n");
  763.     TESTTAILER();
  764.  
  765.     /* calling EMMmappage() with a bad logical page number */
  766.     TESTHEADER();
  767.     printf("Calling EMMmappage(frameno = 0, first handle, logpage = 6).\n");
  768.     printf("Should fail.\n");
  769.     status = EMMmappage(0, handle1, 6);
  770.     nofailcheck("EMMmappage()", status, NULL, handle1, handle2);
  771.     weirdretchk("EMMmappage()", status, NULL, handle1, handle2);
  772.     weirdcodechk("EMMmappage()", EMM_BADLOGPAGE, NULL, handle1, handle2);
  773.     printf("EMMmappage() failed OK.\n");
  774.     TESTTAILER();
  775.  
  776.     TESTHEADER();
  777.     printf("Writing data pattern to page 0, first handle... ");
  778.     FMEMSET(frameptr[0], 0, 16384);
  779.     printf("Verifying... ");
  780.     if (farmemcheck(frameptr[0], 16384, 0) != 0)
  781.     {
  782.         printf("Verify failed!\n");
  783.         test_EMMfree(handle1);
  784.         test_EMMfree(handle2);
  785.         exit(3);
  786.     }
  787.     printf("OK.\n");
  788.     printf("Calling EMMmappage(frameno = 0, first handle, logpage = 1).\n");
  789.     test_EMMmappage(0, handle1, 1);
  790.     printf("EMMmappage() returned OK.\n");
  791.     printf("Writing data pattern to page 1, first handle... ");
  792.     FMEMSET(frameptr[0], 1, 16384);
  793.     printf("Verifying... ");
  794.     if (farmemcheck(frameptr[0], 16384, 1) != 0)
  795.     {
  796.         printf("Verify failed!\n");
  797.         test_EMMfree(handle1);
  798.         test_EMMfree(handle2);
  799.         exit(3);
  800.     }
  801.     printf("OK.\n");
  802.     printf("Now mapping page 0 back, see if it's still OK.\n");
  803.     test_EMMmappage(0, handle1, 0);
  804.     printf("EMMmappage() returned OK, verifying contents... ");
  805.     if (farmemcheck(frameptr[0], 16384, 0) != 0)
  806.     {
  807.         printf("Verify failed!\n");
  808.         test_EMMfree(handle1);
  809.         test_EMMfree(handle2);
  810.         exit(3);
  811.     }
  812.     printf("OK.\n");
  813.     printf("EMMmappage() looks like it's doing something.\n");
  814.     TESTTAILER();
  815.  
  816.     TESTHEADER();
  817.     printf("Testing mapping of all frames...\n");
  818.     printf("Filling rest of allocated pages with unique patterns... ");
  819.     for (loop = 2; loop < 6; loop++)
  820.     {
  821.         test_EMMmappage(0, handle1, loop);
  822.         FMEMSET(frameptr[0], loop, 16384);
  823.         if (farmemcheck(frameptr[0], 16384, (unsigned char) loop) != 0)
  824.         {
  825.             printf("Verify failed on handle 1, page %d.\n", loop);
  826.             test_EMMfree(handle1);
  827.             test_EMMfree(handle2);
  828.             exit(3);
  829.         }
  830.     }
  831.     test_EMMmappage(0, handle2, 0);
  832.     FMEMSET(frameptr[0], 0x10, 16384);
  833.     if (farmemcheck(frameptr[0], 16384, 0x10) != 0)
  834.     {
  835.         printf("Verify failed on handle 2, page 0!\n");
  836.         test_EMMfree(handle1);
  837.         test_EMMfree(handle2);
  838.         exit(3);
  839.     }
  840.     test_EMMmappage(0, handle2, 1);
  841.     FMEMSET(frameptr[0], 0x11, 16384);
  842.     if (farmemcheck(frameptr[0], 16384, 0x11) != 0)
  843.     {
  844.         printf("Verify failed on handle 2, page 1!\n");
  845.         test_EMMfree(handle1);
  846.         test_EMMfree(handle2);
  847.         exit(3);
  848.     }
  849.     printf("Done.\n");
  850.     printf("Mapping handle 1 pages 0-3 in frames 0-3 respectively... ");
  851.     for (loop = 0; loop < 4; loop++)
  852.     {
  853.         test_EMMmappage(loop, handle1, loop);
  854.     }
  855.     printf("Done.\n");
  856.     printf("Verifying contents... ");
  857.     for (loop = 0; loop < 4; loop++)
  858.     {
  859.         if (farmemcheck(frameptr[loop], 16384, (unsigned char) loop) != 0)
  860.         {
  861.             printf("Verify failed for frame %d.\n", loop);
  862.             test_EMMfree(handle1);
  863.             test_EMMfree(handle2);
  864.             exit(3);
  865.         }
  866.     }
  867.     printf("OK.\n");
  868.     printf("Mapping handle 1 pages 0-3 in frames 0-3 in reverse... ");
  869.     for (loop = 0; loop < 4; loop++)
  870.     {
  871.         test_EMMmappage(loop, handle1, (3 - loop));
  872.     }
  873.     printf("Done.\n");
  874.     printf("Verifying contents... ");
  875.     for (loop = 0; loop < 4; loop++)
  876.     {
  877.         if (farmemcheck(frameptr[loop], 16384, (unsigned char)(3 - loop)) != 0)
  878.         {
  879.             printf("Verify failed for frame %d.\n", loop);
  880.             test_EMMfree(handle1);
  881.             test_EMMfree(handle2);
  882.             exit(3);
  883.         }
  884.     }
  885.     printf("OK.\n");
  886.     printf(
  887.       "Mapping handle 1 pages 0-3 in frames 0-3 except page 5 in frame 2... ");
  888.     for (loop = 0; loop < 4; loop++)
  889.     {
  890.         test_EMMmappage(loop, handle1, loop);
  891.     }
  892.     test_EMMmappage(2, handle1, 5);
  893.     printf("Done.\n");
  894.     printf("Verifying contents... ");
  895.     for (loop = 0; loop < 4; loop++)
  896.     {
  897.         if (farmemcheck(frameptr[loop], 16384,
  898.                                  (unsigned char)((loop != 2) ? loop : 5)) != 0)
  899.         {
  900.             printf("Verify failed for frame %d.\n", loop);
  901.             test_EMMfree(handle1);
  902.             test_EMMfree(handle2);
  903.             exit(3);
  904.         }
  905.     }
  906.     printf("OK.\n");
  907.     TESTTAILER();
  908.  
  909.     TESTHEADER();
  910.     printf("Final mapping test... two handles at once!\n");
  911.     printf("Mapping handle2 page 1 in frame 0.\n");
  912.     printf("        handle1 page 4 in frame 1.\n");
  913.     printf("        handle1 page 0 in frame 2.\n");
  914.     printf("        handle2 page 0 in frame 3.\n");
  915.     test_EMMmappage(0, handle2, 1);
  916.     test_EMMmappage(1, handle1, 4);
  917.     test_EMMmappage(2, handle1, 0);
  918.     test_EMMmappage(3, handle2, 0);
  919.     printf("Mapping done. Verifying... ");
  920.     if (farmemcheck(frameptr[0], 16384, 0x11) != 0)
  921.     {
  922.         printf("Verify failed for frame 0.\n");
  923.         test_EMMfree(handle1);
  924.         test_EMMfree(handle2);
  925.         exit(3);
  926.     }
  927.     if (farmemcheck(frameptr[1], 16384, 4) != 0)
  928.     {
  929.         printf("Verify failed for frame 1.\n");
  930.         test_EMMfree(handle1);
  931.         test_EMMfree(handle2);
  932.         exit(3);
  933.     }
  934.     if (farmemcheck(frameptr[2], 16384, 0) != 0)
  935.     {
  936.         printf("Verify failed for frame 2.\n");
  937.         test_EMMfree(handle1);
  938.         test_EMMfree(handle2);
  939.         exit(3);
  940.     }
  941.     if (farmemcheck(frameptr[3], 16384, 0x10) != 0)
  942.     {
  943.         printf("Verify failed for frame 3.\n");
  944.         test_EMMfree(handle1);
  945.         test_EMMfree(handle2);
  946.         exit(3);
  947.     }
  948.     printf("OK.\n");
  949.     TESTTAILER();
  950.  
  951.     /* clean up */
  952.     test_EMMfree(handle1);
  953.     test_EMMfree(handle2);
  954.  
  955.     return;
  956. } /* end of do_map_tests() */
  957.  
  958.  
  959. /***************************************************************************
  960. *   FUNCTION: DO_SR_TESTS                                                  *
  961. *                                                                          *
  962. *   DESCRIPTION:                                                           *
  963. *                                                                          *
  964. *       This function tests the EMSLIB mapping save/restore functions:     *
  965. *       EMMsrinit(), EMMsave(), EMMrestore().                              *
  966. *                                                                          *
  967. *   ENTRY:                                                                 *
  968. *                                                                          *
  969. *       Void.                                                              *
  970. *                                                                          *
  971. *   EXIT:                                                                  *
  972. *                                                                          *
  973. *       Void.                                                              *
  974. *                                                                          *
  975. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  976. *                                                                          *
  977. ***************************************************************************/
  978. void do_sr_tests(void)
  979. {
  980.     void *savehandle;
  981.     int handle1, handle2;
  982.     int status;
  983.     int loop;
  984.  
  985.     /* first, allocate some EMS and fill with unique patterns */
  986.     handle1 = test_EMMallocpages(6);
  987.     handle2 = test_EMMallocpages(2);
  988.     for (loop = 0; loop < 6; loop++)
  989.     {
  990.         test_EMMmappage(0, handle1, loop);
  991.         FMEMSET(frameptr[0], loop, 16384);
  992.         if (farmemcheck(frameptr[0], 16384, (unsigned char) loop) != 0)
  993.         {
  994.             printf("Verify failed on handle 1, page %d.\n", loop);
  995.             test_EMMfree(handle1);
  996.             test_EMMfree(handle2);
  997.             exit(3);
  998.         }
  999.     }
  1000.     test_EMMmappage(0, handle2, 0);
  1001.     FMEMSET(frameptr[0], 0x10, 16384);
  1002.     if (farmemcheck(frameptr[0], 16384, 0x10) != 0)
  1003.     {
  1004.         printf("Verify failed on handle 2, page 0!\n");
  1005.         test_EMMfree(handle1);
  1006.         test_EMMfree(handle2);
  1007.         exit(3);
  1008.     }
  1009.     test_EMMmappage(0, handle2, 1);
  1010.     FMEMSET(frameptr[0], 0x11, 16384);
  1011.     if (farmemcheck(frameptr[0], 16384, 0x11) != 0)
  1012.     {
  1013.         printf("Verify failed on handle 2, page 1!\n");
  1014.         test_EMMfree(handle1);
  1015.         test_EMMfree(handle2);
  1016.         exit(3);
  1017.     }
  1018.  
  1019.     TESTHEADER();
  1020.     printf(
  1021.      "Testing save/restore facility. Calling EMMsave() before EMMsrinit().\n");
  1022.     printf("Should fail.\n");
  1023.     savehandle = EMMsave();
  1024.     nofailcheck("EMMsave()", (int) _EMMerror, NULL, handle1, handle2);
  1025.     weirdcodechk("EMMsave()", EMM_NOSR, NULL, handle1, handle2);
  1026.     printf("EMMsave() failed OK.\n");
  1027.     TESTTAILER();
  1028.  
  1029.     TESTHEADER();
  1030.     printf("Calling EMMsrinit().\nShould succeed.\n");
  1031.     status = EMMsrinit(malloc);
  1032.     TRIPLECHECK("EMMsrinit()", status, 0, NULL, handle1, handle2);
  1033.     printf("EMMsrinit() succeeded; save/restore facility initialized.\n");
  1034.     TESTTAILER();
  1035.  
  1036.     TESTHEADER();
  1037.     printf("Testing EMMsave().\n");
  1038.     printf("Mapping handle 1 pages 0-3 in frames 0-3 respectively.\n");
  1039.     for (loop = 0; loop < 4; loop++)
  1040.     {
  1041.         test_EMMmappage(loop, handle1, loop);
  1042.     }
  1043.  
  1044.     printf("Calling EMMsave() to save current configuration.\n");
  1045.     printf("Should succeed.\n");
  1046.     savehandle = (void *) NULL;
  1047.     savehandle = EMMsave();
  1048.     if (savehandle == (void *) NULL)
  1049.     {
  1050.         printf("EMMsave() did not return anything, code 0x%X.\n",
  1051.                                                      (unsigned int) _EMMerror);
  1052.         test_EMMfree(handle1);
  1053.         test_EMMfree(handle2);
  1054.         exit(3);
  1055.     }
  1056.     weirdcodechk("EMMsave()", 0, NULL, handle1, handle2);
  1057.     printf("EMMsave() succeeded.\n");
  1058.     TESTTAILER();
  1059.  
  1060.     printf("Changing configuration.\n");
  1061.     test_EMMmappage(0, handle2, 1);
  1062.     test_EMMmappage(1, handle1, 4);
  1063.     test_EMMmappage(2, handle1, 0);
  1064.     test_EMMmappage(3, handle2, 0);
  1065.  
  1066.     TESTHEADER();
  1067.     printf("Calling EMMrestore() to restore previous configuration.\n");
  1068.     printf("Should succeed.\n");
  1069.     status = EMMrestore(savehandle);
  1070.     TRIPLECHECK("EMMrestore()", status, 0, NULL, handle1, handle2);
  1071.     printf("EMMrestore() returned OK, verifying contents... ");
  1072.     for (loop = 0; loop < 4; loop++)
  1073.     {
  1074.         if (farmemcheck(frameptr[loop], 16384, (unsigned char) loop) != 0)
  1075.         {
  1076.             printf("Verify failed for frame %d.\n", loop);
  1077.             test_EMMfree(handle1);
  1078.             test_EMMfree(handle2);
  1079.             exit(3);
  1080.         }
  1081.     }
  1082.     printf("OK.\n");
  1083.     TESTTAILER();
  1084.  
  1085.     printf("Cleaning up.\n");
  1086.     test_EMMfree(handle1);
  1087.     test_EMMfree(handle2);
  1088.     free(savehandle);
  1089.  
  1090.     return;
  1091. } /* end of do_sr_tests() */
  1092.  
  1093. #endif
  1094. #endif
  1095.  
  1096.  
  1097. /*
  1098. ** The following group of functions {test_EMM*()} are wrapper functions
  1099. ** that call the EMSLIB function named and perform preliminary checks on
  1100. ** the return values. This keeps code size down since the check only has
  1101. ** to be coded in one place.
  1102. */
  1103.  
  1104. /***************************************************************************
  1105. *   FUNCTION: TEST_EMMCORELEFT                                             *
  1106. *                                                                          *
  1107. *   DESCRIPTION:                                                           *
  1108. *                                                                          *
  1109. *       This function calls EMSLIB function EMMcoreleft() and checks the   *
  1110. *       return value to see if it is a multiple of 16384 (the EMS page     *
  1111. *       size).                                                             *
  1112. *                                                                          *
  1113. *   ENTRY:                                                                 *
  1114. *                                                                          *
  1115. *       Void.                                                              *
  1116. *                                                                          *
  1117. *   EXIT:                                                                  *
  1118. *                                                                          *
  1119. *       Returns the value returned by EMMcoreleft().                       *
  1120. *                                                                          *
  1121. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  1122. *                                                                          *
  1123. ***************************************************************************/
  1124. unsigned long test_EMMcoreleft(void)
  1125. {
  1126.     unsigned long emsfree;
  1127.  
  1128.     /* call EMMcoreleft and check error code */
  1129.     emsfree = EMMcoreleft();
  1130.     weirdcodechk("EMMcoreleft()", 0, NULL, 0, 0);
  1131.  
  1132.     /* check if free byte count is multiple of 16384 */
  1133.     if ((emsfree % 16384L) != 0)
  1134.     {
  1135.         printf("EMMcoreleft() returned strange number %lu.\n", emsfree);
  1136.         exit(3);
  1137.     }
  1138.  
  1139.     return emsfree;
  1140. } /* end of test_EMMcoreleft() */
  1141.  
  1142.  
  1143. /***************************************************************************
  1144. *   FUNCTION: TEST_EMMALLOC                                                *
  1145. *                                                                          *
  1146. *   DESCRIPTION:                                                           *
  1147. *                                                                          *
  1148. *       This function calls EMSLIB function EMMalloc() and checks the      *
  1149. *       return codes.                                                      *
  1150. *                                                                          *
  1151. *   ENTRY:                                                                 *
  1152. *                                                                          *
  1153. *       bytes - bytes of EMS to allocate                                   *
  1154. *                                                                          *
  1155. *   EXIT:                                                                  *
  1156. *                                                                          *
  1157. *       Returns the handle returned by EMMalloc().                         *
  1158. *                                                                          *
  1159. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  1160. *                                                                          *
  1161. ***************************************************************************/
  1162. int test_EMMalloc(unsigned long bytes)
  1163. {
  1164.     int handle;
  1165.  
  1166.     /* call EMMalloc() and check the return */
  1167.     handle = EMMalloc(bytes);
  1168.     weirdcodechk("EMMalloc()", 0, NULL, 0, 0);
  1169.  
  1170.     return handle;
  1171. } /* end of test_EMMalloc() */
  1172.  
  1173.  
  1174. /***************************************************************************
  1175. *   FUNCTION: TEST_EMMALLOCPAGES                                           *
  1176. *                                                                          *
  1177. *   DESCRIPTION:                                                           *
  1178. *                                                                          *
  1179. *       This function calls EMSLIB function EMMallocpages() and checks the *
  1180. *       return codes.                                                      *
  1181. *                                                                          *
  1182. *   ENTRY:                                                                 *
  1183. *                                                                          *
  1184. *       pages - pages of EMS to allocate                                   *
  1185. *                                                                          *
  1186. *   EXIT:                                                                  *
  1187. *                                                                          *
  1188. *       Returns the handle returned by EMMallocpages().                    *
  1189. *                                                                          *
  1190. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  1191. *                                                                          *
  1192. ***************************************************************************/
  1193. int test_EMMallocpages(int pages)
  1194. {
  1195.     int handle;
  1196.  
  1197.     /* call EMMallocpages() and check the return */
  1198.     handle = EMMallocpages(pages);
  1199.     weirdcodechk("EMMallocpages()", 0, NULL, 0, 0);
  1200.  
  1201.     return handle;
  1202. } /* end of test_EMMallocpages() */
  1203.  
  1204.  
  1205. /***************************************************************************
  1206. *   FUNCTION: TEST_EMMFREE                                                 *
  1207. *                                                                          *
  1208. *   DESCRIPTION:                                                           *
  1209. *                                                                          *
  1210. *       This function calls EMSLIB function EMMfree() and checks the       *
  1211. *       return codes.                                                      *
  1212. *                                                                          *
  1213. *   ENTRY:                                                                 *
  1214. *                                                                          *
  1215. *       handle - EMS handle to be freed                                    *
  1216. *                                                                          *
  1217. *   EXIT:                                                                  *
  1218. *                                                                          *
  1219. *       Void.                                                              *
  1220. *                                                                          *
  1221. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  1222. *                                                                          *
  1223. ***************************************************************************/
  1224. void test_EMMfree(int handle)
  1225. {
  1226.     int status;
  1227.  
  1228.     /* call EMMfree() and check the return */
  1229.     status = EMMfree(handle);
  1230.     TRIPLECHECK("EMMfree()", status, 0, NULL, 0, 0);
  1231.  
  1232.     return;
  1233. } /* end of test_EMMfree() */
  1234.  
  1235.  
  1236. /***************************************************************************
  1237. *   FUNCTION: TEST_EMMMAPPAGE                                              *
  1238. *                                                                          *
  1239. *   DESCRIPTION:                                                           *
  1240. *                                                                          *
  1241. *       This function calls EMSLIB function EMMmappage() and checks the    *
  1242. *       return codes.                                                      *
  1243. *                                                                          *
  1244. *   ENTRY:                                                                 *
  1245. *                                                                          *
  1246. *       frameno - frame number to map page into                            *
  1247. *       handle  - handle of page to be mapped                              *
  1248. *       logpage - page number to map                                       *
  1249. *                                                                          *
  1250. *   EXIT:                                                                  *
  1251. *                                                                          *
  1252. *       Void.                                                              *
  1253. *                                                                          *
  1254. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  1255. *                                                                          *
  1256. ***************************************************************************/
  1257. void test_EMMmappage(int frameno, int handle, int logpage)
  1258. {
  1259.     int status;
  1260.  
  1261.     /*
  1262.     ** do sanity check on frame number, just in case -- we shouldn't be
  1263.     ** trying to map into frames other than standard 0 through 3.
  1264.     */
  1265.     if ((frameno < 0) || (frameno > 3))
  1266.     {
  1267.         printf("Sanity check failed, trying to map to frame %d, aborting.\n",
  1268.                                                                       frameno);
  1269.         EMMfree(handle);
  1270.         exit(3);
  1271.     }
  1272.  
  1273.     /* call EMMmappage() and check return */
  1274.     status = EMMmappage(frameno, handle, logpage);
  1275.     TRIPLECHECK("EMMmappage()", status, 0, NULL, handle, 0);
  1276.  
  1277.     return;
  1278. } /* end of test_EMMmappage() */
  1279.  
  1280.  
  1281. /*
  1282. ** The following group of functions are used to speed up return checking
  1283. ** and keep code size down, since the return check only has to be coded
  1284. ** in one place. They are used in various macros to further compact and
  1285. ** clarify the code.
  1286. */
  1287.  
  1288. /***************************************************************************
  1289. *   FUNCTION: WEIRDRETCHK                                                  *
  1290. *                                                                          *
  1291. *   DESCRIPTION:                                                           *
  1292. *                                                                          *
  1293. *       This function checks to see if the status value passed to it is    *
  1294. *       either 0 or EMMOOPS, and assumes something has gone wrong if it    *
  1295. *       is not. If something has gone wrong, does some clean up before     *
  1296. *       exiting.                                                           *
  1297. *                                                                          *
  1298. *   ENTRY:                                                                 *
  1299. *                                                                          *
  1300. *       function - name of function which may have goofed                  *
  1301. *       status   - status value to check                                   *
  1302. *       tofree1  - conventional memory block to be freed on exit. Not      *
  1303. *                  freed if NULL.                                          *
  1304. *       tofree2  - EMS handle to be freed on exit. Not freed if 0.         *
  1305. *       tofree2  - another EMS handle to be freed on exit. Not freed if 0. *
  1306. *                                                                          *
  1307. *   EXIT:                                                                  *
  1308. *                                                                          *
  1309. *       Void, or may not return.                                           *
  1310. *                                                                          *
  1311. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  1312. *                                                                          *
  1313. ***************************************************************************/
  1314. void weirdretchk(char *function, int status, void *tofree1, int tofree2,
  1315.                                                                    int tofree3)
  1316. {
  1317.     if ((status != EMMOOPS) && (status != 0))
  1318.     {
  1319.         printf("%s returned weird value %d, code 0x%X.\n", function, status,
  1320.                                                      (unsigned int) _EMMerror);
  1321.         if (tofree1 != (void *) NULL)
  1322.         {
  1323.             free(tofree1);
  1324.         }
  1325.         if (tofree2 != 0)
  1326.         {
  1327.             EMMfree(tofree2);
  1328.         }
  1329.         if (tofree3 != 0)
  1330.         {
  1331.             EMMfree(tofree3);
  1332.         }
  1333.         exit(3);
  1334.     }
  1335.  
  1336.     return;
  1337. } /* end of weirdretchk() */
  1338.  
  1339.  
  1340. /***************************************************************************
  1341. *   FUNCTION: WEIRDCODECHK                                                 *
  1342. *                                                                          *
  1343. *   DESCRIPTION:                                                           *
  1344. *                                                                          *
  1345. *       This function checks to see if the EMSLIB error code value matches *
  1346. *       the expected value, and assumes something has gone wrong if it     *
  1347. *       does not. If something has gone wrong, does some clean up before   *
  1348. *       exiting.                                                           *
  1349. *                                                                          *
  1350. *   ENTRY:                                                                 *
  1351. *                                                                          *
  1352. *       function - name of function which may have goofed                  *
  1353. *       expected - expected value of _EMMerror                             *
  1354. *       tofree1  - conventional memory block to be freed on exit. Not      *
  1355. *                  freed if NULL.                                          *
  1356. *       tofree2  - EMS handle to be freed on exit. Not freed if 0.         *
  1357. *       tofree2  - another EMS handle to be freed on exit. Not freed if 0. *
  1358. *                                                                          *
  1359. *   EXIT:                                                                  *
  1360. *                                                                          *
  1361. *       Void, or may not return.                                           *
  1362. *                                                                          *
  1363. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  1364. *                                                                          *
  1365. ***************************************************************************/
  1366. void weirdcodechk(char *function, int expected, void *tofree1, int tofree2,
  1367.                                                                    int tofree3)
  1368. {
  1369.     if ((int) _EMMerror != expected)
  1370.     {
  1371.         printf("%s returned unexpected code 0x%X.\n", function,
  1372.                                                      (unsigned int) _EMMerror);
  1373.         if (tofree1 != (void *) NULL)
  1374.         {
  1375.             free(tofree1);
  1376.         }
  1377.         if (tofree2 != 0)
  1378.         {
  1379.             EMMfree(tofree2);
  1380.         }
  1381.         if (tofree3 != 0)
  1382.         {
  1383.             EMMfree(tofree3);
  1384.         }
  1385.         exit(3);
  1386.     }
  1387.  
  1388.     return;
  1389. } /* end of weirdcodechk() */
  1390.  
  1391.  
  1392. /***************************************************************************
  1393. *   FUNCTION: FAILCHECK                                                    *
  1394. *                                                                          *
  1395. *   DESCRIPTION:                                                           *
  1396. *                                                                          *
  1397. *       This function checks to see if the status value passed to it is    *
  1398. *       EMMOOPS and exits if it is. failcheck() is used when a function    *
  1399. *       is expected to succeed. Does some clean up before exiting.         *
  1400. *                                                                          *
  1401. *   ENTRY:                                                                 *
  1402. *                                                                          *
  1403. *       function - name of function which may have goofed                  *
  1404. *       status   - status value to be checked                              *
  1405. *       tofree1  - conventional memory block to be freed on exit. Not      *
  1406. *                  freed if NULL.                                          *
  1407. *       tofree2  - EMS handle to be freed on exit. Not freed if 0.         *
  1408. *       tofree2  - another EMS handle to be freed on exit. Not freed if 0. *
  1409. *                                                                          *
  1410. *   EXIT:                                                                  *
  1411. *                                                                          *
  1412. *       Void, or may not return.                                           *
  1413. *                                                                          *
  1414. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  1415. *                                                                          *
  1416. ***************************************************************************/
  1417. void failcheck(char *function, int status, void *tofree1, int tofree2,
  1418.                                                                   int tofree3)
  1419. {
  1420.     if (status == EMMOOPS)
  1421.     {
  1422.         printf("%s failed, code 0x%X.\n", function, (unsigned int) _EMMerror);
  1423.         if (tofree1 != (void *) NULL)
  1424.         {
  1425.             free(tofree1);
  1426.         }
  1427.         if (tofree2 != 0)
  1428.         {
  1429.             EMMfree(tofree2);
  1430.         }
  1431.         if (tofree3 != 0)
  1432.         {
  1433.             EMMfree(tofree3);
  1434.         }
  1435.         exit(3);
  1436.     }
  1437.  
  1438.     return;
  1439. } /* end of failcheck() */
  1440.  
  1441.  
  1442. /***************************************************************************
  1443. *   FUNCTION: NOFAILCHECK                                                  *
  1444. *                                                                          *
  1445. *   DESCRIPTION:                                                           *
  1446. *                                                                          *
  1447. *       This function checks to see if the status value passed to it is    *
  1448. *       0 and exits if it is. nofailcheck() is used when a function is     *
  1449. *       expected to fail. Does some clean up before exiting.               *
  1450. *                                                                          *
  1451. *   ENTRY:                                                                 *
  1452. *                                                                          *
  1453. *       function - name of function which may have goofed                  *
  1454. *       status   - status value to be checked                              *
  1455. *       tofree1  - conventional memory block to be freed on exit. Not      *
  1456. *                  freed if NULL.                                          *
  1457. *       tofree2  - EMS handle to be freed on exit. Not freed if 0.         *
  1458. *       tofree2  - another EMS handle to be freed on exit. Not freed if 0. *
  1459. *                                                                          *
  1460. *   EXIT:                                                                  *
  1461. *                                                                          *
  1462. *       Void, or may not return.                                           *
  1463. *                                                                          *
  1464. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  1465. *                                                                          *
  1466. ***************************************************************************/
  1467. void nofailcheck(char *function, int status, void *tofree1, int tofree2,
  1468.                                                                   int tofree3)
  1469. {
  1470.     if (status == 0)
  1471.     {
  1472.         printf("%s did not fail.\n", function);
  1473.         if (tofree1 != (void *) NULL)
  1474.         {
  1475.             free(tofree1);
  1476.         }
  1477.         if (tofree2 != 0)
  1478.         {
  1479.             EMMfree(tofree2);
  1480.         }
  1481.         if (tofree3 != 0)
  1482.         {
  1483.             EMMfree(tofree3);
  1484.         }
  1485.         exit(3);
  1486.     }
  1487.  
  1488.     return;
  1489. } /* end of nofailcheck() */
  1490.  
  1491.  
  1492. /*
  1493. ** The following functions are utility functions used to fill and check
  1494. ** blocks of memory and perform other basic services. Many are coded in
  1495. ** in-line assembly language to improve speed. The in-line assembly is
  1496. ** compatible with both Turbo/Borland C[++] and MSC 6.00A. If your compiler
  1497. ** does not support in-line assembly, or the compiler requires an external
  1498. ** assembler which you do not have, the functions contain alternate C code.
  1499. ** In fact, in order to get the in-line assembly, you must define the symbol
  1500. ** INLINE_ASM.
  1501. */
  1502.  
  1503.  
  1504. /***************************************************************************
  1505. *   FUNCTION: FARMEMCHECK                                                  *
  1506. *                                                                          *
  1507. *   DESCRIPTION:                                                           *
  1508. *                                                                          *
  1509. *       This function scans a block of memory looking for bytes which do   *
  1510. *       not match checkchar.                                               *
  1511. *                                                                          *
  1512. *   ENTRY:                                                                 *
  1513. *                                                                          *
  1514. *       buffer    - pointer to block of memory to scan                     *
  1515. *       len       - length of block                                        *
  1516. *       checkchar - value which should be matched                          *
  1517. *                                                                          *
  1518. *   EXIT:                                                                  *
  1519. *                                                                          *
  1520. *       Returns 0 if all bytes match, nonzero if mismatch found.           *
  1521. *                                                                          *
  1522. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  1523. *                                                                          *
  1524. ***************************************************************************/
  1525. int farmemcheck(unsigned char far *buffer, unsigned int len,
  1526.                                                        unsigned char checkchar)
  1527. {
  1528.     int retval = 0;
  1529.     unsigned char huge *temp;
  1530.  
  1531.     /* normalize far pointer and turn into huge pointer */
  1532.     temp = normptr(buffer);
  1533.  
  1534. #ifdef INLINE_ASM
  1535.     ASM  push     bx                    /* preserve registers           */
  1536.     ASM  push     cx
  1537.     ASM  push     si
  1538.     ASM  push     ds
  1539.     ASM  lds      si, [temp]            /* load pointer into DS:SI      */
  1540.     ASM  mov      cx, [len]             /* load length into CX          */
  1541.     ASM  mov      bl, [checkchar]       /* load match value into BX     */
  1542. looptop:
  1543.     ASM  lodsb                          /* load next byte into AL       */
  1544.     ASM  cmp      al, bl                /* test against BL              */
  1545.     ASM  jne      nomatch               /* if not equal, exit loop      */
  1546.     ASM  loop     looptop               /* otherwise loop               */
  1547.     ASM  jmp      match
  1548. nomatch:
  1549.     ASM  mov      retval, 1             /* return nonzero on mismatch   */
  1550. match:
  1551.     ASM  pop      ds                    /* restore register values      */
  1552.     ASM  pop      si
  1553.     ASM  pop      cx
  1554.     ASM  pop      bx
  1555. #else
  1556.     for (; len; len--, temp++)          /* do the same thing in C       */
  1557.     {
  1558.         if (*temp != checkchar)
  1559.         {
  1560.             retval = 1;
  1561.             break;
  1562.         }
  1563.     }
  1564. #endif
  1565.  
  1566.     return retval;
  1567. } /* end of farmemcheck() */
  1568.  
  1569.  
  1570. /***************************************************************************
  1571. *   FUNCTION: FARINCWORDFILL                                               *
  1572. *                                                                          *
  1573. *   DESCRIPTION:                                                           *
  1574. *                                                                          *
  1575. *       Fill a region of memory with incrementing word (16 bit) values.    *
  1576. *       Always starts at 0 value.                                          *
  1577. *                                                                          *
  1578. *   ENTRY:                                                                 *
  1579. *                                                                          *
  1580. *       buffer - pointer to block of memory                                *
  1581. *       len    - length of block, must be even                             *
  1582. *                                                                          *
  1583. *   EXIT:                                                                  *
  1584. *                                                                          *
  1585. *       Void.                                                              *
  1586. *                                                                          *
  1587. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  1588. *                                                                          *
  1589. ***************************************************************************/
  1590. void farincwordfill(unsigned char far *buffer, unsigned int len)
  1591. {
  1592.     unsigned char huge *temp;
  1593. #ifndef INLINE_ASM
  1594.     int loop;
  1595.     int huge *filler;
  1596. #endif
  1597.  
  1598.     /* turn length in bytes into length in words, convert pointer */
  1599.     len /= 2;
  1600.     temp = normptr(buffer);
  1601.  
  1602. #ifdef INLINE_ASM
  1603.     ASM  push     ax                    /* preserve registers           */
  1604.     ASM  push     cx
  1605.     ASM  push     di
  1606.     ASM  push     es
  1607.     ASM  les      di, [temp]            /* load pointer into ES:DI      */
  1608.     ASM  mov      cx, [len]             /* load length into CX          */
  1609.     ASM  xor      ax, ax                /* zero AX                      */
  1610. loop2top:
  1611.     ASM  stosw                          /* store AX in memory, DI += 2  */
  1612.     ASM  inc      ax                    /* increment AX                 */
  1613.     ASM  loop     loop2top              /* loop                         */
  1614.     ASM  pop      es                    /* restore register values      */
  1615.     ASM  pop      di
  1616.     ASM  pop      cx
  1617.     ASM  pop      ax
  1618. #else
  1619.     /* do the same thing in C */
  1620.     for (loop = 0, filler = (int huge *) temp; loop < len; loop++)
  1621.     {
  1622.         *filler = loop;
  1623.     }
  1624. #endif
  1625.  
  1626.     return;
  1627. } /* end of farincwordfill() */
  1628.  
  1629.  
  1630. /***************************************************************************
  1631. *   FUNCTION: FARINCWORDCHECK                                              *
  1632. *                                                                          *
  1633. *   DESCRIPTION:                                                           *
  1634. *                                                                          *
  1635. *       Scans a block of memory to make sure contents are incrementing     *
  1636. *       word values.                                                       *
  1637. *                                                                          *
  1638. *   ENTRY:                                                                 *
  1639. *                                                                          *
  1640. *       buffer - pointer to block of memory                                *
  1641. *       len    - length of block of memory, must be even                   *
  1642. *                                                                          *
  1643. *   EXIT:                                                                  *
  1644. *                                                                          *
  1645. *       Returns 0 if contents are OK, nonzero if mismatch found.           *
  1646. *                                                                          *
  1647. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  1648. *                                                                          *
  1649. ***************************************************************************/
  1650. int farincwordcheck(unsigned char far *buffer, unsigned int len)
  1651. {
  1652.     int retval = 0;
  1653.     unsigned char huge *temp;
  1654. #ifndef INLINE_ASM
  1655.     int loop;
  1656.     int huge *filler;
  1657. #endif
  1658.  
  1659.     /* convert length in bytes to length in words, convert pointer */
  1660.     len /= 2;
  1661.     temp = normptr(buffer);
  1662.  
  1663. #ifdef INLINE_ASM
  1664.     ASM  push     ax                    /* preserve register values     */
  1665.     ASM  push     bx
  1666.     ASM  push     cx
  1667.     ASM  push     si
  1668.     ASM  push     ds
  1669.     ASM  lds      si, [temp]            /* load pointer into DS:SI      */
  1670.     ASM  mov      cx, [len]             /* load length into CX          */
  1671.     ASM  xor      bx, bx                /* zero BX                      */
  1672.     ASM  dec      bx                    /* decrement BX, ready for loop */
  1673. loop3top:
  1674.     ASM  inc      bx                    /* increment BX to next value   */
  1675.     ASM  lodsw                          /* load next word into AX       */
  1676.     ASM  cmp      ax, bx                /* compare word in AX and BX    */
  1677.     ASM  loope    loop3top              /* loop while words are equal   */
  1678.     ASM  je       done                  /* exited loop -- if last cmp   */
  1679.                                         /* was equal, jump to end, else */
  1680.     ASM  mov      retval, 1             /* mismatch, set nonzero retval */
  1681. done:
  1682.     ASM  pop      ds                    /* restore register values      */
  1683.     ASM  pop      si
  1684.     ASM  pop      cx
  1685.     ASM  pop      bx
  1686.     ASM  pop      ax
  1687. #else
  1688.     /* do the same thing in C */
  1689.     for (loop = 0, filler = (int huge *) temp; loop < len; loop++)
  1690.     {
  1691.         if (*filler != loop)
  1692.         {
  1693.             retval = 1;
  1694.             break;
  1695.         }
  1696.     }
  1697. #endif
  1698.  
  1699.     return retval;
  1700. } /* end of farincwordcheck() */
  1701.  
  1702.  
  1703. /***************************************************************************
  1704. *   FUNCTION: FARINCLONGFILL                                               *
  1705. *                                                                          *
  1706. *   DESCRIPTION:                                                           *
  1707. *                                                                          *
  1708. *       Fills a region of memory with incrementing longword (32 bit)       *
  1709. *       values. This function was not coded in assembly because it has     *
  1710. *       to handle regions > 64K, which is a pain in the neck.              *
  1711. *                                                                          *
  1712. *   ENTRY:                                                                 *
  1713. *                                                                          *
  1714. *       buffer - pointer to block of memory                                *
  1715. *       len    - length of block of memory, must be multiple of 4          *
  1716. *       start  - value to start incrementing from                          *
  1717. *                                                                          *
  1718. *   EXIT:                                                                  *
  1719. *                                                                          *
  1720. *       Void.                                                              *
  1721. *                                                                          *
  1722. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  1723. *                                                                          *
  1724. ***************************************************************************/
  1725. void farinclongfill(unsigned char far *buffer, unsigned long len,
  1726.                                                            unsigned long start)
  1727. {
  1728.     unsigned long loop;
  1729.     unsigned long huge *filler;
  1730.  
  1731.     /* convert length in bytes to length in longwords */
  1732.     len /= 4;
  1733.     /* fill */
  1734.     for (loop = 0L, filler = (unsigned long huge *) normptr(buffer);
  1735.                                                   loop < len; loop++, filler++)
  1736.     {
  1737.         *filler = start++;
  1738.     }
  1739.  
  1740.     return;
  1741. } /* end of farinclongfill() */
  1742.  
  1743.  
  1744. /***************************************************************************
  1745. *   FUNCTION: FARINCLONGCHECK                                              *
  1746. *                                                                          *
  1747. *   DESCRIPTION:                                                           *
  1748. *                                                                          *
  1749. *       Scans a region of memory checking that it contains incrementing    *
  1750. *       longword values. This function was not coded in assembly because   *
  1751. *       it has to handle regions > 64K, which is a pain in the neck.       *
  1752. *                                                                          *
  1753. *   ENTRY:                                                                 *
  1754. *                                                                          *
  1755. *       buffer - pointer to block of memory                                *
  1756. *       len    - length of block of memory                                 *
  1757. *       start  - value to start incrementing from                          *
  1758. *                                                                          *
  1759. *   EXIT:                                                                  *
  1760. *                                                                          *
  1761. *       Returns 0 if values OK, nonzero if mismatch found.                 *
  1762. *                                                                          *
  1763. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  1764. *                                                                          *
  1765. ***************************************************************************/
  1766. int farinclongcheck(unsigned char far *buffer, unsigned long len,
  1767.                                                            unsigned long start)
  1768. {
  1769.     unsigned long loop;
  1770.     unsigned long huge *filler;
  1771.     int retval = 0;
  1772.  
  1773.     /* convert length in bytes to length in longwords */
  1774.     len /= 4;
  1775.     /* scan */
  1776.     for (loop = 0L, filler = (unsigned long huge *) normptr(buffer);
  1777.                                                   loop < len; loop++, filler++)
  1778.     {
  1779.         if (*filler != start++)
  1780.         {
  1781.             retval = 1;
  1782.             break;
  1783.         }
  1784.     }
  1785.  
  1786.     return retval;
  1787. } /* end of farinclongcheck() */
  1788.  
  1789.  
  1790. /***************************************************************************
  1791. *   FUNCTION: GET_TICK                                                     *
  1792. *                                                                          *
  1793. *   DESCRIPTION:                                                           *
  1794. *                                                                          *
  1795. *       Retrieves the current timer count via BIOS call. For use when      *
  1796. *       timing copies. The timer ticks 18.2 times per second. The value    *
  1797. *       returned by this function has a jitter of -0,+(1/18.2) seconds.    *
  1798. *                                                                          *
  1799. *   ENTRY:                                                                 *
  1800. *                                                                          *
  1801. *       Void.                                                              *
  1802. *                                                                          *
  1803. *   EXIT:                                                                  *
  1804. *                                                                          *
  1805. *       Returns the timer count.                                           *
  1806. *                                                                          *
  1807. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  1808. *                                                                          *
  1809. ***************************************************************************/
  1810. unsigned long get_tick(void)
  1811. {
  1812.     unsigned long retval;
  1813.  
  1814. #ifdef INLINE_ASM
  1815.     ASM  push     cx                            /* push register values     */
  1816.     ASM  push     dx
  1817.     ASM  xor      ah, ah                        /* AH = 00h, get count call */
  1818.     ASM  int      1Ah                           /* make call                */
  1819.     ASM  mov      WORD PTR [retval + 2], cx     /* save returned value      */
  1820.     ASM  mov      WORD PTR [retval], dx
  1821.     ASM  pop      dx
  1822.     ASM  pop      cx
  1823. #else
  1824.     union REGS r;
  1825.  
  1826.     /* do the same thing in C */
  1827.     r.h.ah = 0x0;
  1828.     int86(0x1A, &r, &r);
  1829.     retval = r.x.cx;
  1830.     retval <<= 16;
  1831.     retval |= r.x.dx;
  1832. #endif
  1833.  
  1834.     return retval;
  1835. } /* end of get_tick() */
  1836.  
  1837.  
  1838. /*
  1839. ** The following group of functions is the same in spirit as the preceding
  1840. ** group, but already exist in the libraries of some compilers. These
  1841. ** functions are only used if the symbol NO_FFUNC is defined, which should
  1842. ** only be done when the compiler's library does not already contain these
  1843. ** functions.
  1844. */
  1845. #ifdef NO_FFUNC
  1846.  
  1847. /***************************************************************************
  1848. *   FUNCTION: FMEMCMP                                                      *
  1849. *                                                                          *
  1850. *   DESCRIPTION:                                                           *
  1851. *                                                                          *
  1852. *       A replacement _fmemcmp() function for compilers which do not have  *
  1853. *       it in their libraries. Compares two regions of memory.             *
  1854. *                                                                          *
  1855. *   ENTRY:                                                                 *
  1856. *                                                                          *
  1857. *       buf1 - pointer to first region                                     *
  1858. *       buf2 - pointer to second region                                    *
  1859. *       n    - length of regions                                           *
  1860. *                                                                          *
  1861. *   EXIT:                                                                  *
  1862. *                                                                          *
  1863. *       Returns 0 on match, negative if mismatch byte in buf1 is less than *
  1864. *       corresponding byte in buf2, positive if vice versa.                *
  1865. *                                                                          *
  1866. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  1867. *                                                                          *
  1868. ***************************************************************************/
  1869. int Fmemcmp(void far *buf1, void far *buf2, unsigned int n)
  1870. {
  1871.     unsigned char huge *temp1, huge *temp2;
  1872.     int retval = 0;
  1873. #ifndef INLINE_ASM
  1874.     int loop;
  1875. #endif
  1876.  
  1877.     /* normalize pointers */
  1878.     temp1 = normptr((unsigned char far *) buf1);
  1879.     temp2 = normptr((unsigned char far *) buf2);
  1880.  
  1881. #ifdef INLINE_ASM
  1882.     ASM  push     cx                    /* preserve register values     */
  1883.     ASM  push     di
  1884.     ASM  push     si
  1885.     ASM  push     ds
  1886.     ASM  push     es
  1887.     ASM  lds      si, [temp1]           /* load first pointer in DS:SI  */
  1888.     ASM  les      di, [temp2]           /* load second pointer in ES:DI */
  1889.     ASM  mov      cx, [n]               /* load length in CX            */
  1890.     ASM  repz     cmpsb                 /* compare while equal          */
  1891.     ASM  jcxz     alldone               /* if CX is 0, all were equal   */
  1892.     ASM  ja       higher                /* not equal, set return value  */
  1893.     ASM  mov      [retval], -1
  1894.     ASM  jmp      alldone
  1895. higher:
  1896.     ASM  mov      [retval], 1
  1897. alldone:
  1898.     ASM  pop      es                    /* restore register values      */
  1899.     ASM  pop      ds
  1900.     ASM  pop      si
  1901.     ASM  pop      di
  1902.     ASM  pop      cx
  1903. #else
  1904.     /* do the same thing in C */
  1905.     for (loop = 0; loop < n; loop++, temp1++, temp2++)
  1906.     {
  1907.         if (*temp1 == *temp2)
  1908.         {
  1909.             continue;
  1910.         }
  1911.         retval = (int) (*temp1 - *temp2);
  1912.         break;
  1913.     }
  1914. #endif
  1915.  
  1916.     return retval;
  1917. } /* end of Fmemcmp() */
  1918.  
  1919.  
  1920. /***************************************************************************
  1921. *   FUNCTION: FMEMSET                                                      *
  1922. *                                                                          *
  1923. *   DESCRIPTION:                                                           *
  1924. *                                                                          *
  1925. *       A replacement _fmemset() function for compilers which do not have  *
  1926. *       it in their libraries. Sets a region of memory to a particular     *
  1927. *       value.                                                             *
  1928. *                                                                          *
  1929. *   ENTRY:                                                                 *
  1930. *                                                                          *
  1931. *       s - pointer to region of memory                                    *
  1932. *       c - byte value to set memory to                                    *
  1933. *       n - length of region                                               *
  1934. *                                                                          *
  1935. *   EXIT:                                                                  *
  1936. *                                                                          *
  1937. *       Returns s.                                                         *
  1938. *                                                                          *
  1939. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  1940. *                                                                          *
  1941. ***************************************************************************/
  1942. void Fmemset(void far *s, int c, unsigned int n)
  1943. {
  1944.     unsigned char huge *temp;
  1945.  
  1946.     /* normalize pointer */
  1947.     temp = normptr((unsigned char far *) s);
  1948.  
  1949. #ifdef INLINE_ASM
  1950.     /* if length is odd, use slower way */
  1951.     if ((n % 2) == 1)
  1952.     {
  1953.         ASM  push     ax                /* preserve register values     */
  1954.         ASM  push     cx
  1955.         ASM  push     di
  1956.         ASM  push     es
  1957.         ASM  les      di, [temp]        /* load pointer into ES:DI      */
  1958.         ASM  mov      al, BYTE PTR [c]  /* load value into AL           */
  1959.         ASM  mov      cx, [n]           /* load length into CX          */
  1960.         ASM  rep      stosb             /* store value in memory        */
  1961.         ASM  pop      es                /* restore register values      */
  1962.         ASM  pop      di
  1963.         ASM  pop      cx
  1964.         ASM  pop      ax
  1965.     }
  1966.     else
  1967.     {
  1968.         /* otherwise use faster way, storing entire words at once */
  1969.         /* convert length in bytes to length in words */
  1970.         n /= 2;
  1971.         ASM  push     ax                /* preserve register values         */
  1972.         ASM  push     cx
  1973.         ASM  push     di
  1974.         ASM  push     es
  1975.         ASM  les      di, [temp]        /* load pointer into ES:DI          */
  1976.         ASM  mov      al, BYTE PTR [c]  /* load value into AL               */
  1977.         ASM  mov      ah, al            /* load value into AH too           */
  1978.         ASM  mov      cx, [n]           /* load length into CX              */
  1979.         ASM  rep      stosw             /* store value in memory by words   */
  1980.         ASM  pop      es                /* restore register values          */
  1981.         ASM  pop      di
  1982.         ASM  pop      cx
  1983.         ASM  pop      ax
  1984.     }
  1985. #else
  1986.     /* do the same thing in C */
  1987.     for (; n; n--, temp++)
  1988.     {
  1989.         *temp = c;
  1990.     }
  1991. #endif
  1992.  
  1993.     return;
  1994. } /* end of Fmemset() */
  1995.  
  1996. #endif
  1997.  
  1998.  
  1999. /***************************************************************************
  2000. *   FUNCTION: NORMPTR  (STATIC)                                            *
  2001. *                                                                          *
  2002. *   DESCRIPTION:                                                           *
  2003. *                                                                          *
  2004. *       Normalizes a far pointer -- reduces the offset to the smallest     *
  2005. *       possible value (somewhere between 0 and 0xF) by adding to the      *
  2006. *       segment.                                                           *
  2007. *                                                                          *
  2008. *   ENTRY:                                                                 *
  2009. *                                                                          *
  2010. *       norm - pointer to be normalized                                    *
  2011. *                                                                          *
  2012. *   EXIT:                                                                  *
  2013. *                                                                          *
  2014. *       Returns normalized pointer.                                        *
  2015. *                                                                          *
  2016. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  2017. *                                                                          *
  2018. ***************************************************************************/
  2019. static unsigned char huge *normptr(unsigned char far *norm)
  2020. {
  2021.     unsigned char huge *retval = (unsigned char huge *) norm;
  2022.  
  2023. #ifdef INLINE_ASM
  2024.     ASM  push     cx                        /* preserve register values */
  2025.     ASM  push     di
  2026.     ASM  push     si
  2027.     ASM  mov      si, WORD PTR [retval]     /* load offset into SI          */
  2028.     ASM  mov      di, si                    /* load offset into DI too      */
  2029.     ASM  mov      cl, 4                     /* load 4 into CL               */
  2030.     ASM  shr      di, cl                    /* shift DI right by 4, which   */
  2031.                                             /* converts it to a segment     */
  2032.     ASM  add      WORD PTR [retval + 2], di /* add to segment in pointer    */
  2033.     ASM  and      si, 0Fh                   /* zero all but lowest nibble   */
  2034.                                             /* of offset                    */
  2035.     ASM  mov      WORD PTR [retval], si     /* put offset back in pointer   */
  2036.     ASM  pop      si                        /* restore register values      */
  2037.     ASM  pop      di
  2038.     ASM  pop      cx
  2039. #else
  2040.     unsigned int segment, offset;
  2041.  
  2042.     /* do the same thing in C -- extract segment and offset from pointer */
  2043.     segment = FP_SEG(retval);
  2044.     offset = FP_OFF(retval);
  2045.     /* add high three nibbles of offset to segment */
  2046.     segment += (offset >> 4);
  2047.     /* preseve only lowest nibble of offset */
  2048.     offset &= 0xF;
  2049.     /* reconstruct pointer from modified segment and offset */
  2050.     retval = MK_FP(segment, offset);
  2051. #endif
  2052.  
  2053.     return retval;
  2054. } /* end of static normptr() */
  2055.  
  2056.